Cleanup device initialization.
Add support for bidirectional virtual consoles.
hypervisor_acknowledge_irq(irq);
ci->ci_ipending |= (1 << irq);
if (ret == 0 && ci->ci_ilevel <
- ci->ci_isources[irq]->is_handlers
- ->ih_level)
+ ci->ci_isources[irq]->is_maxlevel)
ret = 1;
}
#if 0 /* XXXcl dev/evtchn */
netif_tx_interface_t *sc_tx;
netif_rx_interface_t *sc_rx;
+ struct vm_page *sc_pg_tx;
+ struct vm_page *sc_pg_rx;
uint32_t sc_tx_entries;
uint32_t sc_tx_resp_cons;
struct nfs_diskless;
int xennet_scan(struct device *, struct xennet_attach_args *, cfprint_t);
+void xennet_scan_finish(struct device *);
void xennet_start(struct ifnet *);
int xennet_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
void xennet_watchdog(struct ifnet *ifp);
};
int xbd_scan(struct device *, struct xbd_attach_args *, cfprint_t);
+void xbd_scan_finish(struct device *);
#endif /* _XEN_XBDVAR_H_ */
#include <machine/ctrl_if.h>
#include <machine/evtchn.h>
+void printk(char *, ...);
#if 0
-#define DPRINTK(_f, _a...) printf("(file=%s, line=%d) " _f, \
+#define DPRINTK(_f, _a...) printk("(file=%s, line=%d) " _f, \
__FILE__ , __LINE__ , ## _a )
#else
#define DPRINTK(_f, _a...) ((void)0)
*/
int initdom_ctrlif_domcontroller_port = -1;
-static int ctrl_if_evtchn;
+/* static */ int ctrl_if_evtchn = -1;
static int ctrl_if_irq;
static struct simplelock ctrl_if_lock;
while ( ctrl_if_rxmsg_deferred_cons != dp )
{
- msg = &ctrl_if_rxmsg_deferred[MASK_CONTROL_IDX(
- ctrl_if_rxmsg_deferred_cons++)];
+ msg = &ctrl_if_rxmsg_deferred[
+ MASK_CONTROL_IDX(ctrl_if_rxmsg_deferred_cons)];
(*ctrl_if_rxmsg_handler[msg->type])(msg, 0);
+ ctrl_if_rxmsg_deferred_cons++;
}
}
while ( ctrl_if_rx_req_cons != rp )
{
- pmsg = &ctrl_if->rx_ring[MASK_CONTROL_IDX(ctrl_if_rx_req_cons++)];
+ pmsg = &ctrl_if->rx_ring[MASK_CONTROL_IDX(ctrl_if_rx_req_cons)];
memcpy(&msg, pmsg, offsetof(ctrl_msg_t, msg));
DPRINTK("Rx-Req %u/%u :: %d/%d\n",
&msg, offsetof(ctrl_msg_t, msg) + msg.length);
else
(*ctrl_if_rxmsg_handler[msg.type])(&msg, 0);
+
+ ctrl_if_rx_req_cons++;
}
if ( dp != ctrl_if_rxmsg_deferred_prod )
if ( ctrl_if_tx_resp_cons != ctrl_if->tx_resp_prod ||
ctrl_if_rx_req_cons != ctrl_if->rx_req_prod ) {
+#if 0
#if 0
wakeup(&ctrl_if_kthread);
#else
if (ctrl_if_softintr)
softintr_schedule(ctrl_if_softintr);
+#endif
+#else
+ ctrl_if_kthread((void *)1);
#endif
}
control_if_t *ctrl_if = get_ctrl_if();
unsigned long flags;
int i;
+ int s;
save_and_cli(flags);
simple_lock(&ctrl_if_lock);
{
simple_unlock(&ctrl_if_lock);
restore_flags(flags);
- return -EAGAIN;
+ s = splhigh();
+ if ( ctrl_if_tx_resp_cons != ctrl_if->tx_resp_prod )
+ __ctrl_if_tx_tasklet(0);
+ splx(s);
+ return EAGAIN;
}
msg->id = 0xFF;
while ((rc = ctrl_if_send_message_noblock(msg, hnd, id)) == EAGAIN) {
/* XXXcl possible race -> add a lock and ltsleep */
+#if 1
+#else
rc = tsleep((caddr_t) &ctrl_if_tx_wait, PUSER | PCATCH,
"ctrl_if", 0);
if (rc)
break;
+#endif
}
return rc;
{
control_if_t *ctrl_if = get_ctrl_if();
- // printf("ctrl_if_kthread starting\n");
for (;;) {
if ( ctrl_if_tx_resp_cons != ctrl_if->tx_resp_prod )
__ctrl_if_tx_tasklet(0);
if ( ctrl_if_rx_req_cons != ctrl_if->rx_req_prod )
__ctrl_if_rx_tasklet(0);
- if ( ctrl_if_rxmsg_deferred_cons !=
- ctrl_if_rxmsg_deferred_prod )
- __ctrl_if_rxmsg_deferred(NULL);
-
if (arg) {
// printf("ctrl_if_kthread one-shot done\n");
return;
}
static void
-ctrl_if_create_kthread(void *arg)
+ctrl_if_softintr_handler(void *arg)
{
+ static int in_handler = 0;
- printf("ctrl_if_kthread creating\n");
- if (kthread_create1(ctrl_if_kthread, arg, NULL, "ctrl_if"))
- printf("ctrl_if_kthread create failed\n");
- softintr_schedule(ctrl_if_softintr);
+ if (in_handler++ != 0) {
+ ctrl_if_evtchn = -1;
+ panic("recurse");
+ }
+
+ if ( ctrl_if_rxmsg_deferred_cons != ctrl_if_rxmsg_deferred_prod )
+ __ctrl_if_rxmsg_deferred(NULL);
+
+ in_handler--;
}
#ifdef notyet
hypervisor_enable_irq(ctrl_if_irq);
}
+void ctrl_if_early_init(void);
+void ctrl_if_early_init(void)
+{
+
+ simple_lock_init(&ctrl_if_lock);
+
+ ctrl_if_evtchn = xen_start_info.domain_controller_evtchn;
+}
+
void ctrl_if_init(void)
{
- int i;
+ int i;
- for ( i = 0; i < 256; i++ )
- ctrl_if_rxmsg_handler[i] = ctrl_if_rxmsg_default_handler;
+ for ( i = 0; i < 256; i++ )
+ ctrl_if_rxmsg_handler[i] = ctrl_if_rxmsg_default_handler;
- simple_lock_init(&ctrl_if_lock);
+ if (ctrl_if_evtchn == -1)
+ ctrl_if_early_init();
- if (0) kthread_create(ctrl_if_create_kthread, NULL);
- ctrl_if_softintr =
- softintr_establish(IPL_SOFTNET, ctrl_if_kthread, (void *)1);
+ ctrl_if_softintr = softintr_establish(IPL_SOFTNET,
+ ctrl_if_softintr_handler, NULL);
- ctrl_if_resume();
+ ctrl_if_resume();
}
return 0;
}
+static void
+scan_finish(struct device *parent)
+{
+
+#if NXENNET > 0
+ xennet_scan_finish(parent);
+#endif
+#if NXBD > 0
+ xbd_scan_finish(parent);
+#endif
+}
+
/*
* Attach the hypervisor.
*/
xenvfr_init();
}
#endif
+#if NXENNET > 0 || NXBD > 0
+ config_interrupts(self, scan_finish);
+#endif
}
int
#define XEDB_MBUF 0x08
#define XEDB_MEM 0x10
int xennet_debug = 0x0;
-#define DPRINTF(x) if (xennet_debug) printf x;
-#define DPRINTFN(n,x) if (xennet_debug & (n)) printf x;
+void printk(char *, ...);
+#define DPRINTF(x) if (xennet_debug) printk x;
+#define DPRINTFN(n,x) if (xennet_debug & (n)) printk x;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
#endif
+static int
+xennet_wait_for_interfaces(void)
+{
+
+ while (netctrl.xc_interfaces != netctrl.xc_connected)
+ HYPERVISOR_yield();
+ return 0;
+}
+
int
xennet_scan(struct device *self, struct xennet_attach_args *xneta,
cfprint_t print)
{
ctrl_msg_t cmsg;
netif_fe_driver_status_t st;
- int err = 0;
if ((xen_start_info.flags & SIF_INITDOMAIN) ||
(xen_start_info.flags & SIF_NET_BE_DOMAIN))
memcpy(cmsg.msg, &st, sizeof(st));
ctrl_if_send_message_block(&cmsg, NULL, 0, 0);
-#if 0
+ return 0;
+}
+
+void
+xennet_scan_finish(struct device *parent)
+{
+ int err;
+
err = xennet_wait_for_interfaces();
if (err)
ctrl_if_unregister_receiver(CMSG_NETIF_FE, xennet_ctrlif_rx);
-#endif
-
- return err;
}
int
if (xs->sc_ifno == handle)
break;
}
- return xs;
+ return dv ? xs : NULL;
}
static void
{
int respond = 1;
+ DPRINTFN(XEDB_EVENT, ("> ctrlif_rx=%d\n", msg->subtype));
switch (msg->subtype) {
case CMSG_NETIF_FE_INTERFACE_STATUS:
if (msg->length != sizeof(netif_fe_interface_status_t))
xennet_driver_status_change(netif_fe_driver_status_t *status)
{
- DPRINTFN(XEDB_EVENT, ("> status=%d\n", status->status));
+ DPRINTFN(XEDB_EVENT, ("xennet_driver_status_change(%d)\n",
+ status->status));
netctrl.xc_up = status->status;
xennet_driver_count_connected();
netif_fe_interface_connect_t up;
struct xennet_softc *sc;
struct ifnet *ifp;
- struct vm_page *pg_tx, *pg_rx;
struct xennet_attach_args xneta;
- DPRINTFN(XEDB_EVENT, ("> status=%d handle=%d mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ DPRINTFN(XEDB_EVENT, ("xennet_interface_status_change(%d,%d,%02x:%02x:%02x:%02x:%02x:%02x)\n",
status->status,
status->handle,
status->mac[0], status->mac[1], status->mac[2],
}
ifp = &sc->sc_ethercom.ec_if;
+ DPRINTFN(XEDB_EVENT, ("xennet_interface_status_change(%d,%p,%02x:%02x:%02x:%02x:%02x:%02x)\n",
+ status->handle, sc,
+ status->mac[0], status->mac[1], status->mac[2],
+ status->mac[3], status->mac[4], status->mac[5]));
+
switch (status->status) {
case NETIF_INTERFACE_STATUS_CLOSED:
printf("Unexpected netif-CLOSED message in state %d\n",
}
#endif
- /* Move from CLOSED to DISCONNECTED state. */
- sc->sc_tx = (netif_tx_interface_t *)
- uvm_km_valloc_align(kernel_map, PAGE_SIZE, PAGE_SIZE);
- if (sc->sc_tx == NULL)
- panic("netif: no tx va");
- sc->sc_rx = (netif_rx_interface_t *)
- uvm_km_valloc_align(kernel_map, PAGE_SIZE, PAGE_SIZE);
- if (sc->sc_rx == NULL)
- panic("netif: no rx va");
- pg_tx = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
- if (pg_tx == NULL) {
- panic("netif: no tx pages");
- }
- pmap_kenter_pa((vaddr_t)sc->sc_tx, VM_PAGE_TO_PHYS(pg_tx),
- VM_PROT_READ | VM_PROT_WRITE);
- pg_rx = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
- if (pg_rx == NULL) {
- panic("netif: no rx pages");
+ if (sc->sc_backend_state == BEST_CLOSED) {
+ /* Move from CLOSED to DISCONNECTED state. */
+ sc->sc_tx = (netif_tx_interface_t *)
+ uvm_km_valloc_align(kernel_map, PAGE_SIZE, PAGE_SIZE);
+ if (sc->sc_tx == NULL)
+ panic("netif: no tx va");
+ sc->sc_rx = (netif_rx_interface_t *)
+ uvm_km_valloc_align(kernel_map, PAGE_SIZE, PAGE_SIZE);
+ if (sc->sc_rx == NULL)
+ panic("netif: no rx va");
+ sc->sc_pg_tx = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
+ if (sc->sc_pg_tx == NULL) {
+ panic("netif: no tx pages");
+ }
+ pmap_kenter_pa((vaddr_t)sc->sc_tx, VM_PAGE_TO_PHYS(sc->sc_pg_tx),
+ VM_PROT_READ | VM_PROT_WRITE);
+ sc->sc_pg_rx = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
+ if (sc->sc_pg_rx == NULL) {
+ panic("netif: no rx pages");
+ }
+ pmap_kenter_pa((vaddr_t)sc->sc_rx, VM_PAGE_TO_PHYS(sc->sc_pg_rx),
+ VM_PROT_READ | VM_PROT_WRITE);
+ sc->sc_backend_state = BEST_DISCONNECTED;
}
- pmap_kenter_pa((vaddr_t)sc->sc_rx, VM_PAGE_TO_PHYS(pg_rx),
- VM_PROT_READ | VM_PROT_WRITE);
- sc->sc_backend_state = BEST_DISCONNECTED;
/* Construct an interface-CONNECT message for the
* domain controller. */
cmsg.subtype = CMSG_NETIF_FE_INTERFACE_CONNECT;
cmsg.length = sizeof(netif_fe_interface_connect_t);
up.handle = status->handle;
- up.tx_shmem_frame = xpmap_ptom(VM_PAGE_TO_PHYS(pg_tx)) >> PAGE_SHIFT;
- up.rx_shmem_frame = xpmap_ptom(VM_PAGE_TO_PHYS(pg_rx)) >> PAGE_SHIFT;
+ up.tx_shmem_frame = xpmap_ptom(VM_PAGE_TO_PHYS(sc->sc_pg_tx)) >> PAGE_SHIFT;
+ up.rx_shmem_frame = xpmap_ptom(VM_PAGE_TO_PHYS(sc->sc_pg_rx)) >> PAGE_SHIFT;
memcpy(cmsg.msg, &up, sizeof(up));
/* Tell the controller to bring up the interface. */
status->status);
break;
}
+ DPRINTFN(XEDB_EVENT, ("xennet_interface_status_change()\n"));
}
static void
int s;
ringidx = sc->sc_rx->req_prod;
- if (0) printf("network_alloc_rx_buffers prod %d cons %d\n", ringidx,
- sc->sc_rx_resp_cons);
if ((ringidx - sc->sc_rx_resp_cons) > (RX_MAX_ENTRIES / 2))
return;
.subtype = CMSG_BLKIF_FE_DRIVER_STATUS,
.length = sizeof(blkif_fe_driver_status_t),
};
- blkif_fe_driver_status_t *msg = (void*)cmsg.msg;
+ blkif_fe_driver_status_t *msg = (blkif_fe_driver_status_t *)cmsg.msg;
msg->status = ok ? BLKIF_DRIVER_STATUS_UP : BLKIF_DRIVER_STATUS_DOWN;
.subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT,
.length = sizeof(blkif_fe_interface_connect_t),
};
- blkif_fe_interface_connect_t *msg = (void*)cmsg.msg;
+ blkif_fe_interface_connect_t *msg =
+ (blkif_fe_interface_connect_t *)cmsg.msg;
paddr_t pa;
pmap_extract(pmap_kernel(), (vaddr_t)blk_ring, &pa);
diskcookies = pnode;
}
+static int
+xbd_wait_for_interfaces(void)
+{
+
+ while (state != STATE_CONNECTED)
+ HYPERVISOR_yield();
+ return 0;
+}
+
int
xbd_scan(struct device *self, struct xbd_attach_args *mainbus_xbda,
cfprint_t print)
send_driver_status(1);
-#if 0
- enable_update_events(self);
-#endif
-
return 0;
}
+void
+xbd_scan_finish(struct device *parent)
+{
+ int err;
+
+ err = xbd_wait_for_interfaces();
+ if (err)
+ ctrl_if_unregister_receiver(CMSG_NETIF_FE, xbd_ctrlif_rx);
+}
+
#if NXBD > 0
int
xbd_match(struct device *parent, struct cfdata *match, void *aux)
#include <machine/stdarg.h>
#include <machine/xen.h>
#include <machine/hypervisor.h>
+#include <machine/evtchn.h>
+#include <machine/ctrl_if.h>
#include <dev/cons.h>
};
+static void xencons_rx(ctrl_msg_t *, unsigned long);
void xenconscn_attach(void);
int xenconscn_getc(dev_t);
void xenconscn_putc(dev_t, int);
/* Set db_max_line to avoid paging. */
db_max_line = 0x7fffffff;
+
+ (void)ctrl_if_register_receiver(CMSG_CONSOLE, xencons_rx, 0);
}
}
{
struct clist *cl;
int s, len;
- u_char buf[XENCONS_BURST+1];
s = spltty();
if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
* expensive and we don't want our serial ports to overflow.
*/
cl = &tp->t_outq;
- len = q_to_b(cl, buf, XENCONS_BURST);
- (void)HYPERVISOR_console_io(CONSOLEIO_write, len, buf);
+ if (xen_start_info.flags & SIF_INITDOMAIN) {
+ u_char buf[XENCONS_BURST+1];
+
+ len = q_to_b(cl, buf, XENCONS_BURST);
+ (void)HYPERVISOR_console_io(CONSOLEIO_write, len, buf);
+ } else {
+ ctrl_msg_t msg;
+
+ len = q_to_b(cl, msg.msg, sizeof(msg.msg));
+ msg.type = CMSG_CONSOLE;
+ msg.subtype = CMSG_CONSOLE_DATA;
+ msg.length = len;
+ ctrl_if_send_message_noblock(&msg, NULL, 0);
+ /* XXX check return value and queue wait for space
+ * thread/softint */
+ }
s = spltty();
tp->t_state &= ~TS_BUSY;
}
+/* Non-privileged receive callback. */
+static void
+xencons_rx(ctrl_msg_t *msg, unsigned long id)
+{
+ int i;
+ int s;
+ // unsigned long flags;
+ struct xencons_softc *sc;
+ struct tty *tp;
+
+ sc = device_lookup(&xencons_cd, XENCONS_UNIT(cn_tab->cn_dev));
+ if (sc == NULL)
+ goto out;
+
+ tp = sc->sc_tty;
+ if (tp == NULL)
+ goto out;
+
+ s = spltty();
+ // save_and_cli(flags);
+ // simple_lock(&xencons_lock);
+ for (i = 0; i < msg->length; i++)
+ (*tp->t_linesw->l_rint)(msg->msg[i], tp);
+ // simple_unlock(&xencons_lock);
+ // restore_flags(flags);
+ splx(s);
+ out:
+ msg->length = 0;
+ ctrl_if_send_response(msg);
+}
+
+void ctrl_if_early_init(void);
void
xenconscn_attach()
{
cn_tab = &xencons;
+ ctrl_if_early_init();
+
xencons_isconsole = 1;
}
for (;;);
}
-#define MAXLINELEN 1024
void
xenconscn_putc(dev_t dev, int c)
{
- static char buf[1024+1];
- static int bufpos = 0;
-
- buf[bufpos++] = c;
- if (c == '\n') {
- buf[bufpos] = 0;
- (void)HYPERVISOR_console_io(CONSOLEIO_write, bufpos, buf);
- bufpos = 0;
+ extern int ctrl_if_evtchn;
+
+ if (xen_start_info.flags & SIF_INITDOMAIN ||
+ ctrl_if_evtchn == -1) {
+ u_char buf[1];
+
+ buf[0] = c;
+ (void)HYPERVISOR_console_io(CONSOLEIO_write, 1, buf);
+ } else {
+ ctrl_msg_t msg;
+
+ msg.type = CMSG_CONSOLE;
+ msg.subtype = CMSG_CONSOLE_DATA;
+ msg.length = 1;
+ msg.msg[0] = c;
+ while (ctrl_if_send_message_noblock(&msg, NULL, 0) == EAGAIN) {
+ HYPERVISOR_yield();
+ /* XXX check return value and queue wait for space
+ * thread/softint */
+ }
}
}